import threading
import traceback

from loguru import logger

# from biz.cotrs1a.Cotrs_1A_task_mgr import Tbl_1A_queue
from utils.DbHelper2023 import DbHelper

class CommPreemptiveTask:
  C_Failed = 4
  C_NoMore = 0

  def __init__(self, queue_tbl_name, dbHelper:DbHelper, runner, task_type=None, biz_id_fld_name='id'):
    self.queue_tbl_name = queue_tbl_name
    self.biz_id_fld_name = biz_id_fld_name
    self.runner = runner
    self.dbHelper = dbHelper
    self.task_type = task_type
    self.lock1 = threading.Lock()
    self.upd_sts_tmpl = f"update {self.queue_tbl_name} set sts = :sts where id = :id"
    self.upd_sts_tmpl2 = self.upd_sts_tmpl+" and sts = :old_sts"
    stype_where = f" and stype='{self.task_type}'" if self.task_type is not None else ""
    self.get_sts0_min_id_sql = f"select min(id) from {self.queue_tbl_name} where sts=0 {stype_where}"

  def get_sts0_min_id(self):
    rs=self.dbHelper.runSql4All(self.get_sts0_min_id_sql,rs_to_list=True,log=logger)
    return rs[0][0] if rs and len(rs)>0 else None

  def upd_sts(self, task_id, new_sts, old_sts=-1):
    try:
      if old_sts == -1:
        result=self.dbHelper.runSqlWithParas(self.upd_sts_tmpl,{"sts": new_sts, "id": task_id} )
      else:
        result=self.dbHelper.runSqlWithParas(self.upd_sts_tmpl2, {"sts": new_sts, "id": task_id,"old_sts":old_sts})
      return result.rowcount
    except Exception as e:
      logger.error(traceback.format_exc())
      return 0


  def call(self):
    sts0_min_id = ""
    with self.lock1:
      sts0_min_id = self.get_sts0_min_id()
      if sts0_min_id:
        i_upd_cnt = self.upd_sts(sts0_min_id, 1, 0)
        if i_upd_cnt == 0:
          logger.info(f"Failed to preempt task id {sts0_min_id}, giving up this task.")
          return self.C_Failed
      else:
        return self.C_NoMore

    if not sts0_min_id:
      return self.C_NoMore

    biz_id = sts0_min_id
    if self.biz_id_fld_name and self.biz_id_fld_name.lower() != "id":
      sql=f"select {self.biz_id_fld_name} from {self.queue_tbl_name} where id={sts0_min_id}"
      rs=self.dbHelper.run_sql_4result(sql,rs_to_list=True)
      biz_id = rs[0][0] if rs and len(rs)>0 else None
    try:
      if self.runner(biz_id, int(sts0_min_id)):
        i_upd_cnt = self.upd_sts(sts0_min_id, 2)
      else:
        i_upd_cnt = self.upd_sts(sts0_min_id, 4)
    except Exception as e:
      i_upd_cnt = self.upd_sts(sts0_min_id, 4)
      raise e
    return i_upd_cnt


# 执行成功，要返回True，执行失败，要返回False
def runner1( biz_id, task_id):
  logger.info(f"in runner1, biz_id={biz_id}, task_id={task_id}")
  return True

# def test1(test_runner=None):
#   from utils.DbHelper2023 import DbHelper
#   from conf import Config as myconf
#   dbHelper = DbHelper(myconf.mysql_conf,DbHelper.DB_TYPE_MYSQL)
#   inst=CommPreemptiveTask(Tbl_1A_queue, dbHelper, runner1)
#   inst.call()

if __name__ == '__main__':
    pass